package com.qunar.qcf.handler.transport;

import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.qunar.qcf.core.future.ConnectFuture;
import com.qunar.qcf.handler.ResultHandler;
import com.qunar.qcf.socket.nio.NioSocketConnector;

/**
 * client消息发送者
 * 
 * @author zhangwan
 * @email wan.zhang@qunar.com
 * 
 */
public final class ClientSender {
	private final ConnectFuture future;
	private final NioSocketConnector connector;
	private Map<String, ResultHandler> ret;

	public void setRet(Map<String, ResultHandler> ret) {
		this.ret = ret;
	}

	public NioSocketConnector getConnector() {
		return connector;
	}

	public ClientSender(ConnectFuture future, NioSocketConnector connector) {
		this.future = future;
		this.connector = connector;
	}

	private void invoke(String clazz, String method, Object message, ResultHandler result) {
		String key = UUID.randomUUID().toString();
		Transport t = new Transport(clazz, method, message, key);

		ret.put(clazz + method + key, result);

		future.getSession().write(t);
	}
	
	private final Pattern p = Pattern.compile("^tcp://[0-9a-zA-Z\\$]+/[0-9a-zA-Z\\$]+/?$");
	
	public void invoke(String url, Object[] message, ResultHandler result) {
		Matcher m = p.matcher(url);
		if(!m.find())
			throw new ExceptionInInitializerError("wrong tcp protocol.");
		
		String[] params = url.split("/+");
		
		invoke(params[1], params[2], message, result);
	}

	public void invoke(String url, ResultHandler result) {
		invoke(url, null, result);
	}

	/**
	 * 支持同步调用
	 * @param url
	 * @param params
	 * @return
	 */
	public Object get(String url, Object... params) {		
		class Result {
			private Transport o = new Transport();
		}

		final Result ret = new Result();
		synchronized (ret.o) {
			try {
				invoke(url, params, new ResultHandler() {
					@Override
					public void processor(Object message) {
						synchronized (ret.o) {
							ret.o.setMessage(message);
							ret.o.setConnector(connector);
							ret.o.notify();
						}
					}
				});
				ret.o.wait();
			} catch (InterruptedException e) {
			}
			return ret.o;
		}
	}

	public Object get(String url) {
		return get(url, new Object[] {});
	}

}
